package com.ruoyi.SSL.service.impl;

import java.util.ArrayList;
import java.util.List;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ruoyi.SSL.domain.SslApply;
import com.ruoyi.SSL.domain.SslDomainRrVal;
import com.ruoyi.SSL.mapper.SslApplyMapper;
import com.ruoyi.SSL.service.ISslApplyService;
import com.ruoyi.SSL.service.ISslDomainRrValService;
import com.ruoyi.common.utils.CommUtils;
import com.ruoyi.utils.aly.AlyDomainApiUtils;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.Ztree;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.SSL.mapper.SslDomainMapper;
import com.ruoyi.SSL.domain.SslDomain;
import com.ruoyi.SSL.service.ISslDomainService;
import com.ruoyi.common.core.text.Convert;

/**
 * 证书域名管理Service业务层处理
 *
 * @author ruoyi
 * @date 2024-10-12
 */
@Service
public class SslDomainServiceImpl implements ISslDomainService
{
    @Autowired
    private SslDomainMapper sslDomainMapper;
    @Autowired
    private SslApplyMapper sslApplyMapper;

    @Autowired
    private ISslApplyService applyServic;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private ISslApplyService applyService;

    @Autowired
    private ISslDomainRrValService domainRrValService;

    /**
     * 查询证书域名管理
     *
     * @param id 证书域名管理主键
     * @return 证书域名管理
     */
    @Override
    public SslDomain selectSslDomainById(Long id)
    {
        return sslDomainMapper.selectSslDomainById(id);
    }

    /**
     * 查询证书域名管理列表
     *
     * @param sslDomain 证书域名管理
     * @return 证书域名管理
     */
    @Override
    public List<SslDomain> selectSslDomainList(SslDomain sslDomain)
    {
        return sslDomainMapper.selectSslDomainList(sslDomain);
    }

    /**
     * 新增证书域名管理
     *
     * @param sslDomain 证书域名管理
     * @return 结果
     */
    @Override
    public int insertSslDomain(SslDomain sslDomain)
    {
        sslDomain.setCreateTime(DateUtils.getNowDate());
        return sslDomainMapper.insertSslDomain(sslDomain);
    }

    /**
     * 修改证书域名管理
     *
     * @param sslDomain 证书域名管理
     * @return 结果
     */
    @Override
    public int updateSslDomain(SslDomain sslDomain)
    {
        sslDomain.setUpdateTime(DateUtils.getNowDate());
        return sslDomainMapper.updateSslDomain(sslDomain);
    }
    public int updateSslAuthInfoNull(SslDomain sslDomain){
        return sslDomainMapper.updateSslAuthInfoNull(sslDomain);
    }

    /**
     * 批量删除证书域名管理
     *
     * @param ids 需要删除的证书域名管理主键
     * @return 结果
     */
    @Override
    public int deleteSslDomainByIds(String ids)
    {
        for (String id : ids.split(",")) {
            SslApply sslApply = new SslApply();
            sslApply.setMainId(Long.parseLong(id));
            List<SslApply> applyList = sslApplyMapper.selectSslApplyList(sslApply);
            for (SslApply apply : applyList) {
                sslDomainMapper.deleteSslDomainById(apply.getId());
            }
        }
        return sslDomainMapper.deleteSslDomainByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除证书域名管理信息
     *
     * @param id 证书域名管理主键
     * @return 结果
     */
    @Override
    public int deleteSslDomainById(Long id)
    {
        return sslDomainMapper.deleteSslDomainById(id);
    }

    public List<Ztree> selectTree(SslDomain sslDomain){
        List<SslDomain> domainList = sslDomainMapper.selectSslDomainList(sslDomain);
        return initZtree(domainList);
    }

    /**
     * 对象转部门树
     *
     * @param domainList 服务器列表
     * @return 树结构列表
     */
    public List<Ztree> initZtree(List<SslDomain> domainList)
    {
        List<Ztree> ztrees = new ArrayList<Ztree>();
        for (SslDomain domain : domainList)
        {
            if (!domain.getStatus().equals("D"))
            {
                Ztree ztree = new Ztree();
                ztree.setId(domain.getId());
                ztree.setpId(0L);
                ztree.setName(domain.getCertificateDomain());
                ztree.setTitle(domain.getCertificateDomain());
                ztrees.add(ztree);
            }
        }
        return ztrees;
    }


    public SslDomain getByDomain(SslApply sslApply){
        //通过域名查找记录
        SslDomain sslDomain = new SslDomain();
        sslDomain.setCertificateDomain(sslApply.getCertificateDomain());
        List<SslDomain> sslDomainList = sslDomainMapper.selectSslDomainList(sslDomain);
        if(sslDomainList != null && sslDomainList.size() > 0){
            sslDomain = sslDomainList.get(0);
        }else {
            //插入数据
            sslDomain.setIsUniversal(sslApply.getIsUniversal());
            sslDomain.setIssuingAuthority(sslApply.getIssuingAuthority());
            insertSslDomain(sslDomain);
        }
        return sslDomain;
    }


    /**
     * 第一次启动自动续签执行的方法
     * @param sslDomain
     */
    public AjaxResult firstEnableAutoSSL(SslDomain sslDomain){
        //判断当前域名是否已经满足重新续签的条件或者是新的域名
        JSONObject applyObjJson = JSONUtil.parseObj(JSONUtil.toJsonStr(sslDomain));
        //创建申请时，自动去把账户注册了 //判断SSL证书厂家
        if(applyObjJson.getStr("issuingAuthority").equals("LetsEncryptSSL")) {
            try {
                //重新申请域名
                AjaxResult aj = applyServic.insertSslApply(applyObjJson);
                if(aj.isSuccess()){
                    //保存到域名记录中
                    sslDomain.setSslApplyId(Long.parseLong(aj.get("data").toString()));
                    sslDomain.setStatus("-1");
                    //更新数据
                    updateSslDomain(sslDomain);
                    aj.put("applyId", Long.parseLong(aj.get("data").toString()));
                    return aj;
                }else{
                    return aj;
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return AjaxResult.error("未知错误！");
    }

    /**
     * 申请证书的方法
     * @param domain 域名对象
     */
    public AjaxResult applySSL(SslDomain domain){
        try {
            //获取到参数
            String platformDomain = configService.selectConfigByKey("platform.domain");
            if(StringUtils.isBlank(platformDomain) ){
                return AjaxResult.error("平台公用参数配置有误！");
            }
            //判断CA厂商
            if(StrUtil.equals(domain.getIssuingAuthority(), "LetsEncryptSSL")) {
                //转换参数类型
                JSONObject applyObjJson = JSONUtil.parseObj(JSONUtil.toJsonStr(domain));
                //重新申请域名
                AjaxResult aj = applyServic.insertSslApply(applyObjJson);
                if (aj.isSuccess()) {
                    //保存到域名记录中
                    domain.setSslApplyId(Long.parseLong(aj.get("data").toString()));
                    domain.setStatus("0");
                    //更新数据
                    updateSslDomain(domain);
                    aj.put("applyId", Long.parseLong(aj.get("data").toString()));
                    return aj;
                }
                return aj;
            }else{
                return AjaxResult.error("暂不支持【"+domain.getIssuingAuthority()+"】CA厂商！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("发起证书申请错误！");
        }
    }


    /**
     * 通过域名与服务器id查询域名记录
     * @return 返回查询到的域名
     */
    public SslDomain getByDomain(JSONObject sslInfo, String sslFileUrl, String privateFileUrl){
        SslDomain sslDomain = new SslDomain();
        sslDomain.setCertificateDomain(sslInfo.getStr("domainTxt"));
        List<SslDomain> domainList = selectSslDomainList(sslDomain);
        if(domainList != null && domainList.size() > 0){
            sslDomain = domainList.get(0);
        }else{
            sslDomain.setDeployStatus("Y");
            sslDomain.setPrivateKeyType(sslInfo.getStr("signTypeName"));
            sslDomain.setIssuingAuthority(sslInfo.getStr("ca"));
            sslDomain.setExpiredTime(DateUtil.parse(sslInfo.getStr("endTime")));
            sslDomain.setIsUniversal(sslInfo.getStr("domainTxt").contains("*")?"Y":"N");
            //判断证书是否过期
            if(sslDomain.getExpiredTime().before(DateUtil.date())){
                sslDomain.setStatus("4");
            }else{
                sslDomain.setStatus("3");
            }
            //插入一个同步来源的证书申请记录
            SslApply sslApply = new SslApply();
            sslApply.setExpiredTime(sslDomain.getExpiredTime());
            sslApply.setCertificateDomain(sslDomain.getCertificateDomain());
            sslApply.setPrivateKeyType(sslDomain.getPrivateKeyType());
            sslApply.setIssuingAuthority(sslDomain.getIssuingAuthority());
            sslApply.setSslFilePath(privateFileUrl+","+sslFileUrl);
            sslApply.setStatus("3");
            //先插入域名数据
            insertSslDomain(sslDomain);
            //赋值归属域名
            sslApply.setMainId(sslDomain.getId());
            //插入数据
            sslApplyMapper.insertSslApply(sslApply);
            sslDomain.setSslApplyId(sslApply.getId());
            //更新数据
            updateSslDomain(sslDomain);
        }
        return sslDomain;
    }


    public AjaxResult applyBefor(String domainName){
        //先判断域名格式是否正确
        if(!CommUtils.isValidDomain(domainName)){
            return AjaxResult.error("域名格式错误！");
        }
        //判断系统参数
        String platformDomain = configService.selectConfigByKey("platform.domain");
        if(StrUtil.isBlank(platformDomain)){
            return AjaxResult.error("平台公用参数配置有误！");
        }
        //判断当前域名是否是根级域名
        List<String> domainTxtList = new ArrayList<>();
        AjaxResult aj = applyService.isHaveSpecialDomain(domainName);
        //得到根级域名
        String domainRoot = "";
        if(aj.isSuccess()){
            domainRoot = String.valueOf(aj.get("data"));
        }else{
            String domainTmp = domainName.substring(0, domainName.lastIndexOf("."));
            String domainSuffix = domainName.substring(domainName.lastIndexOf("."));
            domainRoot = domainTmp.contains(".")?domainTmp.split("\\.")[domainTmp.split("\\.").length-1]+domainSuffix:domainTmp+domainSuffix;
        }
        String domainTmp = domainName.replace("."+domainRoot, "").replace(domainRoot, "")
                .replaceAll("\\*.", "").replaceAll("\\*", "");
        if(!domainName.contains("*")){
            if(StrUtil.isBlank(domainTmp)){
                //判断是否包含www
                domainTxtList.add("");
                domainTxtList.add(".www");
            }else{
                if(StrUtil.isNotBlank(domainTmp)&&StringUtils.equals(domainTmp, "www")){
                    //判断是否包含www
                    domainTxtList.add("");
                    domainTxtList.add(".www");
                }else{
                    domainTxtList.add("."+domainTmp);
                }
            }
        }else {
            domainTxtList.add(StrUtil.isNotBlank(domainTmp)?"."+domainTmp:domainTmp);
        }
        List<JSONObject> rrValList = new ArrayList<>();
        //判断是否需要解析两条记录
        for (String domainTxt : domainTxtList) {
            //循环生成验证信息
            JSONObject jsonObject = new JSONObject();
            //随机生成一个主机记录值用于用户解析
            String rrKeyVal = RandomUtil.randomStringWithoutStr(9, "4").toLowerCase();
            //判断是否是泛域名
            jsonObject.set("domainName", domainRoot);
            String rrVal = "";
            if(StrUtil.isBlank(domainTxt)){
                jsonObject.set("rrKeyWord", "_acme-challenge");
                rrVal = rrKeyVal+"."+platformDomain;
            } else {
                jsonObject.set("rrKeyWord", "_acme-challenge"+domainTxt);
                rrVal = rrKeyVal+domainTxt+"."+platformDomain;
            }
            aj = applyService.getDomainRrVal(StrUtil.isBlank(domainTxt)?domainTxt+domainRoot:domainTxt.substring(1)+"."+domainRoot, rrVal);
            if(!aj.isSuccess()){
                return aj;
            }
            jsonObject.set("rrVal", String.valueOf(aj.get("data")));
            rrValList.add(jsonObject);
        }
        return AjaxResult.success("查询", rrValList);
    }
}
